﻿using System;
using System.Collections.Generic;
using System.IO;
using GeoAPI.Geometries;
using GeoAPI.IO;
using RTools_NTS.Util;

namespace YJKGridTopologyCal.IO
{
	public class WKBHexFileReader
	{
		public WKBHexFileReader(IBinaryGeometryReader wkbReader)
		{
			if (wkbReader == null)
			{
				throw new System.ArgumentNullException("wkbReader");
			}
			this.Limit = -1;
			this._wkbReader = wkbReader;
		}

		public int Limit { get; set; }

		public int Offset { get; set; }

		public ICollection<IGeometry> Read(string file)
		{
			if (string.IsNullOrEmpty(file))
			{
				throw new System.ArgumentNullException("file");
			}
			ICollection<IGeometry> result;
			using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
			{
				result = this.Read(fileStream);
			}
			return result;
		}

		public ICollection<IGeometry> Read(Stream stream)
		{
			if (stream == null)
			{
				throw new System.ArgumentNullException("stream");
			}
			if (!stream.CanRead)
			{
				throw new Exception("Stream must be readable");
			}
			if (!stream.CanSeek)
			{
				throw new Exception("Stream must be seekable");
			}
			ICollection<IGeometry> result;
			using (StreamReader streamReader = new StreamReader(stream))
			{
				result = this.Read(streamReader);
			}
			return result;
		}

		private ICollection<IGeometry> Read(StreamReader streamReader)
		{
			List<IGeometry> list = new List<IGeometry>();
			int num = 0;
			while (!WKBHexFileReader.IsAtEndOfFile(streamReader) && !this.IsAtLimit(list))
			{
				string text = streamReader.ReadLine();
				if (!string.IsNullOrEmpty(text))
				{
					IGeometry item = this._wkbReader.Read(WKBReader.HexToBytes(text));
					if (num >= this.Offset)
					{
						list.Add(item);
					}
					num++;
				}
			}
			return list;
		}

		private bool IsAtLimit(ICollection<IGeometry> geoms)
		{
			return this.Limit >= 0 && geoms.Count >= this.Limit;
		}

		private static bool IsAtEndOfFile(StreamReader bufferedReader)
		{
			long position = bufferedReader.BaseStream.Position;
			Token token;
			if (!new StreamTokenizer(bufferedReader).NextToken(out token) || token is EofToken)
			{
				return true;
			}
			bufferedReader.BaseStream.Seek(position, SeekOrigin.Begin);
			return false;
		}

		private readonly IBinaryGeometryReader _wkbReader;
	}
}
